﻿using Architecture.Domain.Services.Interface;
using Architecture.Domian.Common;
using Architecture.Domian.DTO;
using Architecture.Domian.Entity;
using Architecture.Repository;
using Architecture.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Architecture.Domain.Services.Impl
{
    public class MenuService : IMenuService
    {
        private readonly IMenuRepository _menuRepository;
        private readonly IRoleRepository _roleRepository;
        private readonly IRepository<RoleMenuRelation> _relationRepository;

        public MenuService(
            IMenuRepository menuRepository,
            IRoleRepository roleRepository,
            IRepository<RoleMenuRelation> relationRepository)
        {
            _menuRepository = menuRepository;
            _roleRepository = roleRepository;
            _relationRepository = relationRepository;
        }

        public List<MenuListDTO> GetMenuInfoDTOs(int parentId)
        {
            var res = _menuRepository.GetAsync(x => x.ParentId.Equals(parentId)).Result.Select(x => new MenuListDTO
            {
                Value = x.MenuId,
                Label = x.MenuName,
                ParentId = x.ParentId,
                Children = GetMenuInfoDTOs(x.MenuId).Count > 0 ? GetMenuInfoDTOs(x.MenuId) : null,
            });
            return res.ToList();
        }

        public List<MenuListDTO> GetMenuListDTO()
        {
            var menuList = new List<MenuListDTO>();
            menuList.Add(new MenuListDTO
            {
                Value = 0,
                Label = "权限菜单",
                ParentId = -1,
                Children = GetMenuInfoDTOs(0)
            });
            return menuList;
        }

        public async Task<int> MenuInsert(MenuInfo menuInfo)
        {
            var exist = await _menuRepository.GetByFuncAsync(x => x.MenuName.Equals(menuInfo.MenuName));
            if (exist != null) return -1;
            menuInfo.CreateBy = "张三";
            menuInfo.CreateDate = DateTime.Now;
            menuInfo.UpdateBy = null;
            menuInfo.UpdateDate = null;
            var res = await _menuRepository.AddAsync(menuInfo);
            return res;
        }

        public async Task<PageResult<MenuInfoDTO>> GetPage(int size, int index)
        {
            var menuInfo = _menuRepository.GetAllAsync().Result.Select(x => new MenuInfoDTO
            {
                MenuId = x.MenuId,
                MenuName = x.MenuName,
                MenuURL = x.MenuURL,
                ParentId = x.ParentId,
                CreateBy = x.CreateBy,
                CreateDate = x.CreateDate,
                UpdateBy = x.UpdateBy,
                UpdateDate = x.UpdateDate,
                SortBy = x.SortBy,
            }).ToArray();

            foreach (var item in menuInfo)
            {
                // 父级Id为0，该项为顶级菜单，则输出null
                if (item.ParentId == 0)
                {
                    item.MenuParentName = "权限菜单" + "=>" + item.MenuName;
                    continue;
                }
                // 父级Id不为0，则输出父级菜单名称 => 本身菜单名称
                var parentName = _menuRepository.GetByFuncAsync(menu => menu.MenuId.Equals(item.ParentId)).Result.MenuName;
                item.MenuParentName = parentName + "=>" + item.MenuName;
            }

            int totalCount = menuInfo.Count();
            int pageCount = (int)Math.Ceiling(totalCount * 1.0 / size);

            menuInfo = menuInfo.OrderByDescending(x => x.MenuId).Skip(size * (index - 1)).Take(size).ToArray();

            return new PageResult<MenuInfoDTO>
            {
                TotalCount = totalCount,
                PageCount = pageCount,
                Datas = menuInfo.ToList()
            };
        }

        public async Task<MenuInfo> GetMenuInfo(int menuId)
        {
            var res = _menuRepository.GetByIdAsync(menuId);
            return await res;
        }

        public async Task<int> UpdateMenuInfo(MenuInfo menuInfo)
        {
            var exist = await _menuRepository.GetByFuncAsync(x => x.ParentId.Equals(menuInfo.ParentId) && x.MenuName.Equals(menuInfo.MenuName) && x.MenuId != menuInfo.MenuId);
            if (exist != null) return -1;
            menuInfo.UpdateBy = "李四";
            menuInfo.UpdateDate = DateTime.Now;
            var res = _menuRepository.UpdateAsync(menuInfo);
            return await res;
        }

        // 判断是否存在子级菜单信息
        public async Task<int> DeleteMenuInfo(int menuId)
        {
            // 判断是否存在子项菜单信息
            var exist = _menuRepository.GetByFuncAsync(x => x.ParentId.Equals(menuId)).Result;
            if (exist != null) return -1;// 该菜单有子项菜单

            // 删除与该菜单相关联的权限信息
            var res = await DeletePression(menuId);
            res += await DeleteMenuByMenuId(menuId);
            return res;
        }

        // 删除菜单信息
        private async Task<int> DeleteMenuByMenuId(int menuId)
        {
            var menuInfo = await _menuRepository.GetByIdAsync(menuId);
            return await _menuRepository.DeleteAsync(menuInfo);
        }


        // 删除菜单信息（包含本身）
        public async Task<int> DeleteMenu(int menuId)
        {
            // 删除与该菜单相关联的权限信息
            await DeletePression(menuId);
            // 删除该菜单的所有子项菜单
            var menuAll = await _menuRepository.GetAsync(x => x.ParentId.Equals(menuId));
            var res = await _menuRepository.BatchDeleteAsync(menuAll);
            // 删除本身
            res += await DeleteMenuByMenuId(menuId);
            return res;
        }

        // 删除与该菜单相关联的权限信息
        private async Task<int> DeletePression(int menuId)
        {
            var pressionAll = await _relationRepository.GetAsync(x => x.MenuId.Equals(menuId));
            return await _relationRepository.BatchDeleteAsync(pressionAll);
        }

        public List<TreeList> GetRoleTree()
        {
            var roleTree = from a in _roleRepository.GetAllAsync().Result
                           where !a.IsDelete
                           select new TreeList()
                           {
                               Id = a.RoleId,
                               Label = a.RoleName,
                           };
            return roleTree.ToList();
        }

        public async Task<int> PressionInsert(int roleId, List<int> menuIds)
        {
            // 删除该角色下所有权限信息
            var pressionByRole = await _relationRepository.GetAsync(x => x.RoleId.Equals(roleId));
            await _relationRepository.BatchDeleteAsync(pressionByRole);
            // 重新添加角色权限信息
            var res = 0;
            foreach (var menuId in menuIds)
            {
                RoleMenuRelation info = new RoleMenuRelation()
                {
                    RoleId = roleId,
                    MenuId = menuId,
                };
                res += await _relationRepository.AddAsync(info);
            }
            return res;
        }

        public List<int> GetMenuIdsByRoleId(int roleId)
        {
            var menuIds = _relationRepository.GetAsync(x => x.RoleId.Equals(roleId)).Result.Select(x => x.MenuId);
            return menuIds.ToList();
        }

        public async Task<List<MenuListDTO>> GetMenuListDTOByMenuName(string? menuName)
        {
            if (string.IsNullOrEmpty(menuName))
            {
                return GetMenuListDTO();
            }
            var res = await _menuRepository.GetByFuncAsync(x => x.MenuName.Contains(menuName));
            var menuList = new List<MenuListDTO>
            {
                new MenuListDTO
                {
                    Value = res.MenuId,
                    Label = res.MenuName,
                    ParentId = res.ParentId,
                    Children = GetMenuInfoDTOs(res.MenuId)
                }
            };
            return menuList;
        }
    }
}
